○DLLの作成

Win32 Dynamic-Link Library
単純なDLLプロジェクトを選択
DllMain の前に以下を追加

-----------------------------------ここから-----------------------------------
int intPos;

extern "C" __declspec(dllexport) int getInt(void){
return intPos;
}

extern "C" __declspec(dllexport) void setInt(int b){
	intPos=b;
}

extern "C" __declspec(dllexport) void mbox(char*a){
::MessageBox(NULL,a,"hello", MB_OK);
}

#include <string.h>
char str[1024]="";
extern "C" __declspec(dllexport) char* out(char*a,char*b){
	strcat(str,a);
	strcat(str,b);
	return str;
}


----------------------------------ここまで-------------------------------------
ビルドしてDLLを作成します。

○DLLの動的呼び出し

上で作成した ○○○.dll ファイルを実行ファイルのあるディレクトリに移動します。

void DllCall()
{
	typedef int (*GETINT)(void);	//関数ポインタの構造体の宣言
	typedef void (*SETINT)(int);
	typedef void(*MBOX)(char*);
	typedef char*(*OUTCHAR)(char*,char*);

	//DLLをロードできないときは次のをためしてみる
	//typedef int (__stdcall*GETINT)(void);

	//アドレス空間内にマップする
	HINSTANCE hDllInstance = ::LoadLibrary("testdll.dll");//DLLを指定

	// エクスポートされた関数のアドレスを取得
	GETINT getInt=(GETINT)::GetProcAddress(hDllInstance, "getInt"); //関数ポインタとDLLの関数の結びつけ
	SETINT setInt=(SETINT)::GetProcAddress(hDllInstance, "setInt");
	MBOX mbox=(MBOX)::GetProcAddress(hDllInstance, "mbox");
	OUTCHAR out=(OUTCHAR)::GetProcAddress(hDllInstance, "out");
			
	printf("%s\n",out("aa","bb"));//後は普通の関数のように呼び出せます。

	FreeLibrary(hDllInstance);//開放
}


○呼び出し規約の違い
関数の引数はスタックに積まれて渡されますが、最後に誰がスタックを戻すかにより
呼び出し規則が変わります。

■DLLのソース

//スタックの後処理を呼び出し側が行う呼び出し規則
extern "C" __declspec(dllexport) int __cdecl a(int i){
	return i;
}

//スタックの後処理を関数側が行う呼び出し規則
//WINDOWSのAPIなどと同じ呼び出し規則
extern "C" __declspec(dllexport) int __stdcall b(int i){
	return i;
}

■上のDLLを呼び出すプログラム
呼び出し規則によりDLLを呼び出す側の対応も必要になります

	typedef int (__cdecl *A)(int);	//関数ポインタの構造体の宣言
	typedef int (__stdcall *B)(int);	//関数ポインタの構造体の宣言
	HINSTANCE hDllInstance = LoadLibrary("test.dll");//DLLを指定
	A a=(A)GetProcAddress(hDllInstance, "a");
	B b=(B)GetProcAddress(hDllInstance, "_b@4");//エクスポートされた名前を調べる必要がある
	printf("%d\n",a(1));
	printf("%d\n",b(2));
	FreeLibrary(hDllInstance);

エキスポートされた名前を調べるには、このプログラムを使いました
DLLの関数名を表示 実行ファイル+ソース

○APIもDLLのため、呼び出し規則をあわせれば同様に呼び出せます
次のプログラムではMessageBoxAをDLLの呼び出しと同じように呼び出します

	typedef int (__stdcall *FUNC)(HWND,LPCSTR,LPCSTR,UINT);	//関数ポインタの構造体の宣言
	HINSTANCE hDllInstance = LoadLibrary("user32.dll");//DLLを指定
	FUNC func=(FUNC)GetProcAddress(hDllInstance, "MessageBoxA");
	func(NULL,"a","b",1);





▲トップページ > Windows と C++